package cn.yunbamboos.mybatis.mapping;


import cn.yunbamboos.mybatis.annotation.CustomDelete;
import cn.yunbamboos.mybatis.annotation.CustomInsert;
import cn.yunbamboos.mybatis.annotation.CustomQuery;
import cn.yunbamboos.mybatis.annotation.CustomUpdate;
import cn.yunbamboos.mybatis.mapping.methods.BaseMethod;
import cn.yunbamboos.mybatis.mapping.methods.custom.CustomDeleteMethod;
import cn.yunbamboos.mybatis.mapping.methods.custom.CustomInsertMethod;
import cn.yunbamboos.mybatis.mapping.methods.custom.CustomQueryMethod;
import cn.yunbamboos.mybatis.mapping.methods.custom.CustomUpdateMethod;
import cn.yunbamboos.mybatis.mapping.methods.delete.DeleteByPrimaryKey;
import cn.yunbamboos.mybatis.mapping.methods.delete.DeleteByPrimaryKeys;
import cn.yunbamboos.mybatis.mapping.methods.dynamicQuery.QueryForList;
import cn.yunbamboos.mybatis.mapping.methods.dynamicQuery.QueryForObject;
import cn.yunbamboos.mybatis.mapping.methods.dynamicQuery.QueryForPage;
import cn.yunbamboos.mybatis.mapping.methods.dynamiccount.CountForPage;
import cn.yunbamboos.mybatis.mapping.methods.insert.Insert;
import cn.yunbamboos.mybatis.mapping.methods.query.QueryAllList;
import cn.yunbamboos.mybatis.mapping.methods.query.QueryByPrimaryKey;
import cn.yunbamboos.mybatis.mapping.methods.query.QueryByPrimaryKeys;
import cn.yunbamboos.mybatis.mapping.methods.update.Update;
import cn.yunbamboos.mybatis.metadata.TableInfo;
import org.apache.ibatis.session.Configuration;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class GenericMapping {

    private final List<BaseMethod> methods = new ArrayList<>();
    private final Configuration configuration;
    private final TableInfo tableInfo;

    public GenericMapping(Configuration configuration, TableInfo tableInfo) {
        this.configuration = configuration;
        this.tableInfo = tableInfo;
        this.addDefaultMethods();
    }

    private void addDefaultMethods() {
        // 1.queryAllList 查询所有的方法
        this.methods.add(new QueryAllList(configuration, tableInfo));
        // 2.Insert 插入记录
        this.methods.add(new Insert(configuration, tableInfo));
        // 3.更新记录
        this.methods.add(new Update(configuration, tableInfo));
        // 4.queryByPrimaryKey
        this.methods.add(new QueryByPrimaryKey(configuration, tableInfo));
        // 5.queryByPrimaryKeys
        this.methods.add(new QueryByPrimaryKeys(configuration, tableInfo));
        // 6.deleteByPrimaryKey
        this.methods.add(new DeleteByPrimaryKey(configuration, tableInfo));
        // 7.deleteByPrimaryKeys
        this.methods.add(new DeleteByPrimaryKeys(configuration, tableInfo));
        // 8.queryForObject
        this.methods.add(new QueryForObject(configuration, tableInfo));
        // 9.queryForList
        this.methods.add(new QueryForList(configuration, tableInfo));
        // 10.countForPage
        this.methods.add(new CountForPage(configuration, tableInfo));
        // 11.queryForPage
        this.methods.add(new QueryForPage(configuration, tableInfo));
    }

    public void addCustomInsertMethod(Method method, CustomInsert insert) {
        String methodName = method.getName();
        CustomInsertMethod custom = new CustomInsertMethod(methodName, configuration, tableInfo);
        custom.setSql(insert.sql());
        this.methods.add(custom);
    }

    public void addCustomDeleteMethod(Method method, CustomDelete delete) {
        String methodName = method.getName();
        CustomDeleteMethod custom = new CustomDeleteMethod(methodName, configuration, tableInfo);
        custom.setSql(delete.sql());
        this.methods.add(custom);
    }

    public void addCustomUpdateMethod(Method method, CustomUpdate update) {
        String methodName = method.getName();
        CustomUpdateMethod custom = new CustomUpdateMethod(methodName, configuration, tableInfo);
        custom.setSql(update.sql());
        this.methods.add(custom);
    }

    public void addCustomQueryMethod(Method method, CustomQuery query) {
        String methodName = method.getName();
        CustomQueryMethod custom = new CustomQueryMethod(methodName, configuration, tableInfo);
        custom.setSql(query.sql());
        custom.setResultType(query.resultType());
        this.methods.add(custom);
    }

    public void addGenerateMethod(BaseMethod method) {
        this.methods.add(method);
    }


    public void exec() {
        methods.forEach(BaseMethod::exec);
    }

}
